package top.lc951.myglide.load;

import android.support.annotation.VisibleForTesting;

public class Engine {

    private final EngineJobFactory engineJobFactory;

    @VisibleForTesting
    public void shutdown() {
        engineJobFactory.shutdown();
        diskCacheProvider.clearDiskCacheIfCreated();
        activeResources.shutdown();
    }

    @VisibleForTesting
    static class EngineJobFactory {
        @Synthetic final GlideExecutor diskCacheExecutor;
        @Synthetic final GlideExecutor sourceExecutor;
        @Synthetic final GlideExecutor sourceUnlimitedExecutor;
        @Synthetic final GlideExecutor animationExecutor;
        @Synthetic final EngineJobListener engineJobListener;
        @Synthetic final ResourceListener resourceListener;

        @Synthetic
        final Pools.Pool<EngineJob<?>> pool =
                FactoryPools.threadSafe(
                        JOB_POOL_SIZE,
                        new FactoryPools.Factory<EngineJob<?>>() {
                            @Override
                            public EngineJob<?> create() {
                                return new EngineJob<>(
                                        diskCacheExecutor,
                                        sourceExecutor,
                                        sourceUnlimitedExecutor,
                                        animationExecutor,
                                        engineJobListener,
                                        resourceListener,
                                        pool);
                            }
                        });

        EngineJobFactory(
                GlideExecutor diskCacheExecutor,
                GlideExecutor sourceExecutor,
                GlideExecutor sourceUnlimitedExecutor,
                GlideExecutor animationExecutor,
                EngineJobListener engineJobListener,
                ResourceListener resourceListener) {
            this.diskCacheExecutor = diskCacheExecutor;
            this.sourceExecutor = sourceExecutor;
            this.sourceUnlimitedExecutor = sourceUnlimitedExecutor;
            this.animationExecutor = animationExecutor;
            this.engineJobListener = engineJobListener;
            this.resourceListener = resourceListener;
        }

        @VisibleForTesting
        void shutdown() {
            Executors.shutdownAndAwaitTermination(diskCacheExecutor);
            Executors.shutdownAndAwaitTermination(sourceExecutor);
            Executors.shutdownAndAwaitTermination(sourceUnlimitedExecutor);
            Executors.shutdownAndAwaitTermination(animationExecutor);
        }

        @SuppressWarnings("unchecked")
        <R> EngineJob<R> build(
                Key key,
                boolean isMemoryCacheable,
                boolean useUnlimitedSourceGeneratorPool,
                boolean useAnimationPool,
                boolean onlyRetrieveFromCache) {
            EngineJob<R> result = Preconditions.checkNotNull((EngineJob<R>) pool.acquire());
            return result.init(
                    key,
                    isMemoryCacheable,
                    useUnlimitedSourceGeneratorPool,
                    useAnimationPool,
                    onlyRetrieveFromCache);
        }
    }
}
